package com.gc.ip;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import com.gc.ip.util.IntegerKeyListener;

@SuppressWarnings("serial")
public class JIPv4Editor extends JPanel implements IPEditor
{
	private static final int DEFAULT_PREFIX_LENGTH = 0;
	
	private JIPv4TextField ipv4TextField = null;
	
	private boolean hasPrefixLength = false;
	private JTextField prefixLenTextField = null;
	
	public JIPv4Editor(boolean hasPrefixLength)
	{
		this.hasPrefixLength = hasPrefixLength;
		
		initGUI();
		addListeners();
	}
	
	public JIPv4Editor()
	{
		this(false);
	}
	
	private void initGUI()
	{
		//IPv4 Text Field
		ipv4TextField = new JIPv4TextField();
		
		//Add it to the center
		this.setLayout(new BorderLayout());
		this.add(ipv4TextField, BorderLayout.CENTER);
		
		//Add the prefix length panel if needed
		if(hasPrefixLength)
		{
			//initialize prefixLenTextField
			prefixLenTextField = new JTextField();
			prefixLenTextField.setColumns(2);
			prefixLenTextField.setHorizontalAlignment(JTextField.TRAILING);
			prefixLenTextField.setFocusable(true);
			prefixLenTextField.setRequestFocusEnabled(true);
			prefixLenTextField.setToolTipText("0-32");
			prefixLenTextField.setText(String.valueOf(DEFAULT_PREFIX_LENGTH));

			JPanel prefixLenPanel = new JPanel();
			prefixLenPanel.setLayout(new BorderLayout());
			JLabel sepLabel = new JLabel("/");
			sepLabel.setFont(ipv4TextField.getFont());
			prefixLenPanel.add(sepLabel, BorderLayout.WEST);
			prefixLenPanel.add(prefixLenTextField, BorderLayout.CENTER);
			
			this.add(prefixLenPanel, BorderLayout.EAST);
		}
	}
	
	private void addListeners()
	{
		ipv4TextField.addPropertyChangeListener(TEXT_PROPERTY, new IPv4PropertyChangeListener());
		
		if(hasPrefixLength)
		{
			prefixLenTextField.addKeyListener(new IntegerKeyListener(0, 32));
			prefixLenTextField.addFocusListener(new PrefixLengthFocusListener());
			prefixLenTextField.getDocument().addDocumentListener(new PrefixLengthDocumentListener());
		}
	}
	
	@Override
	public IPAddress getIPAddress()
	{
		IPAddress ipAddress = new IPAddress(ipv4TextField.getIp());
		if(hasPrefixLength)
		{
			String prefixText = prefixLenTextField.getText();
			
			int prefixLengthVal = -1;
			try
			{
				prefixLengthVal = Integer.parseInt(prefixText);
				if(prefixLengthVal < 0 || prefixLengthVal > 32)
				{
					prefixLengthVal = DEFAULT_PREFIX_LENGTH;
				}
			}
			catch(NumberFormatException e)
			{
				prefixLengthVal = DEFAULT_PREFIX_LENGTH;
			}
			ipAddress.setPrefixLength(prefixLengthVal);
		}
		return ipAddress;
	}

	@Override
	public void setIPAddress(IPAddress ipAddress)
	{
		if(ipAddress == null || ipAddress.getIPType() != IPType.IPv4)
		{
			ipv4TextField.setIp("");
			if(hasPrefixLength)
			{
				prefixLenTextField.setText(String.valueOf(DEFAULT_PREFIX_LENGTH));
			}

			return;
		}
		ipv4TextField.setIp(ipAddress.getStrAddr());
		if(hasPrefixLength)
		{
			int prefixLengthVal = ipAddress.getPrefixLength();
			if(prefixLengthVal < 0 || prefixLengthVal > 32)
			{
				prefixLengthVal = DEFAULT_PREFIX_LENGTH;
			}
			prefixLenTextField.setText(String.valueOf(prefixLengthVal));
		}
	}

	@Override
	public JComponent getUiComponent()
	{
		return this;
	}
	
	@Override
	public void setEnabled(boolean enabled)
	{
		super.setEnabled(enabled);
		ipv4TextField.setEnabled(enabled);
		if(this.hasPrefixLength)
		{
			prefixLenTextField.setEnabled(enabled);
		}
	}
	
	private void prefixLengthChanged()
	{
		IPAddress ipAddress = getIPAddress();
		
		putClientProperty(IP_ADDRESS_PROPERTY, ipAddress);
		putClientProperty(IP_TYPE_PROPERTY, ipAddress.getIPType());
		
		String text = ipv4TextField.getText();
		if(hasPrefixLength)
		{
			text += "/" + prefixLenTextField.getText();
		}
		putClientProperty(TEXT_PROPERTY, text);
	}
	
	private class IPv4PropertyChangeListener implements PropertyChangeListener
	{
		@Override
		public void propertyChange(PropertyChangeEvent event)
		{
			if(TEXT_PROPERTY.equals(event.getPropertyName()))
			{
				IPAddress ipAddress = getIPAddress();
				
				putClientProperty(IP_ADDRESS_PROPERTY, ipAddress);
				putClientProperty(IP_TYPE_PROPERTY, ipAddress.getIPType());
				
				String text = ipv4TextField.getText();
				if(hasPrefixLength)
				{
					text += "/" + prefixLenTextField.getText();
				}
				putClientProperty(TEXT_PROPERTY, text);
			}
		}
	}
	
	private class PrefixLengthDocumentListener implements DocumentListener
	{
		public void insertUpdate(DocumentEvent e)
		{
			prefixLengthChanged();
		}
		public void removeUpdate(DocumentEvent e)
		{
			prefixLengthChanged();
		}
		public void changedUpdate(DocumentEvent e)
		{
			prefixLengthChanged();
		}
	}
	
	private class PrefixLengthFocusListener implements FocusListener
	{
		public void focusGained(FocusEvent e)
		{
		}
		public void focusLost(FocusEvent e)
		{
			String text = prefixLenTextField.getText();
			if(text == null || text.isEmpty())
			{
				prefixLenTextField.setText(String.valueOf(DEFAULT_PREFIX_LENGTH));
			}
		}
	}

	public static void main(String[] args)
	{
		JFrame frame = new JFrame("Demo");

		JIPv4Editor tableDemo = new JIPv4Editor(true);
		tableDemo.setIPAddress(new IPAddress("10.25.25.89", 9));
		frame.getContentPane().add(tableDemo);

		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setPreferredSize(new Dimension(300, 57));
		frame.pack();
		frame.setVisible(true);
	}
}
